<!--
 * @Description: 通用表格操作 搜索,表格,翻页
 * @version: 电子名片2.0
 * @Author: 付小清
 * @Date: 2020-12-04 16:03:32
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-11-18 10:58:27
-->
<template>
  <div>
    <!-- 表单 -->
    <div v-if="searchShow" class="search-box">
      <el-form
        v-if="!searchs.length"
        :inline="true"
        :size="size"
        :model="_formInline"
        :validate-on-rule-change="false"
        class="demo-form-inline"
      >
        <slot name="search" />
        <el-form-item v-if="searchBtn">
          <el-button type="primary" @click="onSubmit">查询</el-button>
          <el-button type="default" @click="onReset">重置</el-button>
        </el-form-item>
        <slot name="button" />
      </el-form>
      <!-- 搜索框 -->
      <search
        v-else
        :search="searchs"
        @get-list="getList"
        @init-params="onReset()"
      >
        <slot slot="param" name="param" />
        <slot slot="button" name="button">
          <el-button v-if="otherShow" type="success" @click="$emit('add-list')">添加</el-button>
        </slot>
      </search>
    </div>
    <!-- 表格 -->
    <div class="table-box">
      <el-table
        ref="refTable"
        v-loading="loading"
        :data="_tableData"
        style="width: 100%"
        :border="true"
        :size="size"
        :highlight-current-row="true"
        :header-cell-style="headerCellStyle"
        @selection-change="selectionChange"
        @row-click="rowClick"
      >
        <template v-if="tableColumn.length">
          <template v-for="item in tableColumn">
            <el-table-column
              v-if="item.isTemplate"
              :key="item.prop"
              :prop="item.prop"
              :label="item.label"
              :fixed="item.fixed"
              align="center"
            >
              <slot slot-scope="scope" :name="item.prop" :value="scope.row" />
            </el-table-column>
            <el-table-column
              v-else
              :key="item.prop"
              :prop="item.prop"
              :label="item.label"
              :fixed="item.fixed"
              align="center"
            />
          </template>
        </template>
        <template v-else>
          <slot name="column" />
        </template>
        <!-- 暂无内容替换区域 -->
        <template slot="empty">
          <slot name="empty" />
        </template>
      </el-table>
      <!-- 翻页 -->
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :current-page="_pageInfo.current"
        :page-sizes="sizes"
        :page-size="_pageInfo.size"
        :total="_pageInfo.total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script>
import search from './search.vue'
export default {
  components: {
    search
  },
  props: {
    searchShow: {
      type: Boolean,
      default: true
    },
    searchBtn: {
      type: Boolean,
      default: true
    },
    otherShow: {
      type: Boolean,
      default: true
    },
    formInline: {
      type: Object,
      default: () => {
        return {}
      }
    },
    searchs: {
      type: Array,
      default: () => {
        return []
      }
    },
    // table头部
    tableColumn: {
      type: Array,
      default: () => {
        return []
      }
    },
    // table数据
    tableData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 默认翻页
    pageInfo: {
      type: Object,
      default: () => {
        return {
          current: 1, // 页数
          size: 20, // 大小
          total: 0 // 总数
        }
      }
    },
    // 请求参数
    param: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 选中
    selectionList: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 请求方法
    apiFun: {
      type: Function,
      default() {
        return new Function()
      }
    },
    // 请求返回参数数据处理
    filterOut: {
      type: Function,
      default() {
        return new Function()
      }
    },
    // 重置
    resetFun: {
      type: Function,
      default() {
        return new Function()
      }
    }
  },
  data() {
    return {
      sizes: [10,20, 50, 100],
      loading: false,
      headerCellStyle: {
        background: '#eef1f6',
        color: '#606266',
        textAlign: 'center'
      }
    }
  },
  computed: {
    size() {
      return this.$store.getters.size
    },
    _tableData: {
      get() {
        return this.tableData
      },
      set(value) {
        this.$emit('update:tableData', value)
      }
    },
    _pageInfo: {
      get() {
        return this.pageInfo
      },
      set(value) {
        this.$emit('update:pageInfo', value)
      }
    },
    _formInline: {
      get() {
        return this.formInline
      },
      set(value) {
        this.$emit('update:formInline', value)
      }
    },
    _selectionList: {
      get() {
        return this.selectionList
      },
      set(value) {
        this.$emit('update:selectionList', value)
      }
    }
  },
  watch: {
    _selectionList: {
      handler(val) {
        this.toggleRowSelection()
      }
    },
    _tableData: {
      handler(val) {
        this.toggleRowSelection()
      }
    }
  },
  mounted() {
    this.getList()
  },
  methods: {
    // 多选
    selectionChange(val) {
      this._selectionList = val
    },
    // 设置默认选中
    toggleRowSelection() {
      this.$nextTick(() => {
        this._tableData.forEach((row, i) => {
          let status = true
          // table数据列表循环选中列表里有没
          this._selectionList.forEach((item) => {
            if (JSON.stringify(row) === JSON.stringify(item)) {
              status = false
            }
          })
          if (status) {
            this.$refs.refTable.toggleRowSelection(this.tableData[i], false)
          } else {
            this.$refs.refTable.toggleRowSelection(this.tableData[i], true)
          }
        })
      })
    },
    // 点击行选中
    rowClick(row) {
      let status = true
      this._selectionList.forEach((item, index) => {
        if (JSON.stringify(row) === JSON.stringify(item)) {
          status = false
          this._selectionList.splice(index, 1)
        }
      })
      if (status) {
        this._selectionList.push(row)
      }
      this.toggleRowSelection()
    },
    // 查询
    onSubmit() {
      this.getList()
      
    },
    // 重置
    onReset() {
      // 重置方法有些参数重置不为空,需要特殊处理,返回true，默认是underfind
      const isExist = JSON.stringify(this.resetFun(this._formInline))
      if (!isExist) {
        for (const x in this._formInline) {
          // 参数是空删除
          this._formInline[x] = ''
        }
      }
      this.getList()
    },
    // 当前页数
    handleSizeChange(e) {
      this._pageInfo.size = e
      this.getList()
    },
    // 当前大小
    handleCurrentChange(e) {
      this._pageInfo.current = e
      this.getList()
    },
    // 列表请求
    async getList(param) {
      let params = {
        ...this._formInline,
        current: this._pageInfo.current,
        size: this._pageInfo.size
      }
      if (param) {
        params = {
          ...params,
          ...param
        }
        this._pageInfo.current = 1
      }
      this.loading = true
      if (!this.apiFun) {
        // 判断请求是否存在
        setTimeout(() => {
          this.loading = false
        }, 200)
        return console.warn('apiFun 为空, apiFun is not available')
      }
      try {
        const { data } = await this.apiFun(params)
        const res = data || []
        // 判断方法是否有数据返回
        if (JSON.stringify(this.filterOut(res))) {
          // 数据重置
          if (!this.filterOut(res)) {
            this.loading = false
            return
          }
          this._tableData = this.filterOut(res)
        } else {
          this._tableData = res.list
        }
        // 翻页
        this._pageInfo.total = data.total || 0
        this.loading = false
        return Promise.resolve()
      } catch (e) {
        console.warn(e)
        // 出错返回信息
        this._tableData = []
        this.loading = false
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.el-pagination {
  margin-top: 15px;
  text-align: right;
}
.search-box .search-box{padding: 0 0 22px; margin-bottom: 0;}
</style>
